/*
 * @Author: your name
 * @Date: 2021-03-17 11:48:25
 * @LastEditTime: 2021-06-23 15:51:33
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \vue-element-admin\src\permission.js
 */
import router from "./router";
import store from "./store";
import { Message } from "element-ui";
import NProgress from "nprogress"; // progress bar
import "nprogress/nprogress.css"; // progress bar style
import { getToken } from "@/utils/auth"; // get token from cookie
import getPageTitle from "@/utils/get-page-title";
// 其实在路由守卫中，只有next()是放行，其他的诸如：next('/logon') 、 next(to) 或者 next({ ...to, replace: true })都不是放行，而是：中断当前导航，执行新的导航
// next() 是放行，但是如果next()里有参数的话，next()就像被重载一样，就有了不同的功能。
NProgress.configure({ showSpinner: false }); // NProgress Configuration

const whiteList = ["/login", "/auth-redirect"]; // no redirect whitelist
// 用户登录成功之后，我们会在全局钩子router.beforeEach中拦截路由，判断是否已获得token，在获得token之后我们就要去获取用户的基本信息了
// 页面 会先从cookie中 查看是否存有 token，没有，就走一遍 重新登录的流程 如果有token,就会把这个 token 返给后端去拉取user_info，保证用户信息是最新的
router.beforeEach(async (to, from, next) => {
  // start progress bar
  NProgress.start();

  // set page title
  document.title = getPageTitle(to.meta.title);

  // determine whether the user has logged in
  const hasToken = getToken();

  if (hasToken) {
    if (to.path === "/login") {
      // if is logged in, redirect to the home page
      // 有token在地址栏 手动输入login--还是到首页
      next({ path: "/" });
      NProgress.done(); // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939
    } else {
      // determine whether the user has obtained his permission roles through getInfo
      // 确定用户是否已通过getInfo获得其权限角色 判断当前用户是否已拉取完user_info信息
      const hasRoles = store.getters.roles && store.getters.roles.length > 0;
      if (hasRoles) {
        next(); //resolve 钩子
      } else {
        try {
          // get user info
          // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
          const { roles } = await store.dispatch("user/getInfo"); // 拉取user_info

          // generate accessible routes map based on roles
          //基于用户角色生成可访问的路由
          const accessRoutes = await store.dispatch(
            "permission/generateRoutes",
            roles
          );
          console.log(accessRoutes, "accessRoutes");
          // dynamically add accessible routes
          // 动态添加可访问路由
          router.addRoutes(accessRoutes);
          // 这里还有一个小hack的地方，就是router.addRoutes之后的next()可能会失效，因为可能next()的时候路由并没有完全add完成，好在查阅文档发现
          // hack method to ensure that addRoutes is complete //// hack方法 确保addRoutes已完成
          // set the replace: true, so the navigation will not leave a history record //设置replace:true，这样导航就不会留下历史记录
          next({ ...to, replace: true }); // 中断当前导航，执行新的导航
        } catch (error) {
          // remove token and go to login page to re-login
          await store.dispatch("user/resetToken");
          Message.error(error || "Has Error");
          next(`/login?redirect=${to.path}`);
          NProgress.done();
        }
      }
    }
  } else {
    /* has no token 去登录页面 重新登录*/

    if (whiteList.indexOf(to.path) !== -1) {
      //在免登录白名单，直接进入
      // in the free login whitelist, go directly
      next();
    } else {
      // other pages that do not have permission to access are redirected to the login page.
      // 其他没有访问权限的页面被重定向到登录页面。
      next(`/login?redirect=${to.path}`);
      NProgress.done();
    }
  }
});

router.afterEach(() => {
  // finish progress bar
  NProgress.done();
});
